package com.chhuang.utils.httpRequest;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

/**
 * HttpURLConnection封装工具类
 * 
 * @author HuangChen
 *
 */
public class HttpUtil {

	public static final String SERVLET_POST = "POST" ;
	public static final String SERVLET_GET = "GET" ; 
	public static final String SERVLET_DELETE = "DELETE" ;
	public static final String SERVLET_PUT = "PUT" ;

	public static final String UTF_8 = "UTF-8" ;
	public static final String CONTENT_TYPE = "Content-Type";
	public static final String USER_AGENT = "User-Agent";
	public static final String ACCEPT_ENCODING = "Accept-Encoding";
	public static final String ACCEPT_LANGUAGE = "Accept-Language";
	public static final String CHARSET = "Charset";
	public static final String CONNECTION = "Connection";
	public static final String REFERER = "Referer";
	public static final String ACCEPT = "Accept";
	public static final String RANGE = "Range";
	public static final String SET_COOKIE = "Set-Cookie";
	public static final String COOKIE = "Cookie";
	public static final String HOST = "Host";
	public static final String UPGRADE = "Upgrade";

    private static final int TIME_OUT = 60000;
	private static final String PREFIX = "--";
    private static final String LINE_END = "\r\n";
	public static final String BOUNDARY = "*****";
	public static final String TEXT_PLAIN= "text/plain; charset=utf-8";
	public static final String KEEP_ALIVE = "Keep-Alive";
	public static final String MULTIPAT_FORMDATA= "multipart/form-data; boundary=" + BOUNDARY;
	private static final String ACCEPT_VALUE = "*/*";
      
	/**
	 * 拼接请求参数
	 * 
	 * @param paramMap
	 * @return
	 */
    public static String prepareParam(Map<String,Object> paramMap){
        StringBuffer sb = new StringBuffer();
        if(paramMap==null || paramMap.isEmpty()){
            return null ;
        }else{
            for(String key: paramMap.keySet()){
                String value = (String)paramMap.get(key);
                if(sb.length()<1){
                    sb.append(key).append("=").append(value);
                }else{
                    sb.append("&").append(key).append("=").append(value);
                }
            }
            return sb.toString();
        }
    }
    
    /**
     * post提交数据
     * 
     * @param urlStr
     * @param paramMap
     * @return
     * @throws Exception
     */
    public static HttpURLConnection doPost(String urlStr, Map<String,Object> params, Map<String,String> propertys) throws IOException{  
    	URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod(SERVLET_POST);
        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setConnectTimeout(TIME_OUT);
        /*setRequestProperty*/
        conn.setRequestProperty(CONTENT_TYPE, TEXT_PLAIN);
        if (propertys!=null && !propertys.isEmpty()){
            for (String key : propertys.keySet()) {  
            	conn.setRequestProperty(key, propertys.get(key));
            }
        }
        /*设置参数*/
        String paramStr = prepareParam(params);
        if(paramStr!=null && !"".equals(paramStr)){
            OutputStream os = conn.getOutputStream();       
            os.write(paramStr.toString().getBytes(UTF_8));
            os.flush();
            os.close();
        }
        
        return conn; 
    }  
    
    /**
     * get提交数据
     * 
     * @param urlStr
     * @param paramMap
     * @return
     * @throws Exception
     */
    public static HttpURLConnection doGet(String urlStr, Map<String,Object> params, Map<String,String> propertys) throws IOException{  
    	/*设置参数*/
    	String paramStr = prepareParam(params);
    	if(paramStr!=null && !"".equals(paramStr)){
    		urlStr +="?"+paramStr;
        }
    	
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod(SERVLET_GET);
        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setDoOutput(false);
        conn.setConnectTimeout(TIME_OUT);
        /*setRequestProperty*/
        conn.setRequestProperty(CONTENT_TYPE, TEXT_PLAIN);
        if (propertys!=null && !propertys.isEmpty()){
            for (String key : propertys.keySet()) {  
            	conn.setRequestProperty(key, propertys.get(key));  
            }
        }
        
        return conn;
    }  
    
    /**
     * put提交数据
     * 
     * @param urlStr
     * @param paramMap
     * @return
     * @throws Exception
     */
    public static HttpURLConnection doPut(String urlStr, Map<String,Object> params, Map<String,String> propertys) throws IOException{  
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
        conn.setRequestMethod(SERVLET_PUT);
        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setConnectTimeout(TIME_OUT);
        /*setRequestProperty*/
        conn.setRequestProperty(CONTENT_TYPE, TEXT_PLAIN);
        if (propertys!=null && !propertys.isEmpty()){
            for (String key : propertys.keySet()) {  
            	conn.setRequestProperty(key, propertys.get(key));
            }
        }
        /*设置参数*/
        String paramStr = prepareParam(params);
        if(paramStr!=null && !"".equals(paramStr)){
            OutputStream os = conn.getOutputStream();       
            os.write(paramStr.toString().getBytes(UTF_8));
            os.flush();
            os.close();
        }
        
        return conn;       
    }  
    
    /**
     * delete提交数据
     * 
     * @param urlStr
     * @param paramMap
     * @return
     * @throws IOException 
     * @throws Exception
     */
    public static HttpURLConnection doDelete(String urlStr, Map<String,Object> params, Map<String,String> propertys) throws IOException{ 
    	/*设置参数*/
    	String paramStr = prepareParam(params);
    	if(paramStr!=null && !"".equals(paramStr)){
    		urlStr +="?"+paramStr;
        }
    	
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod(SERVLET_DELETE);
        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setConnectTimeout(TIME_OUT);
        
        /*setRequestProperty*/
        conn.setRequestProperty(CONTENT_TYPE, TEXT_PLAIN);
        if (propertys!=null && !propertys.isEmpty()){
            for (String key : propertys.keySet()) {
            	conn.setRequestProperty(key, propertys.get(key));  
            }
        }
        
        return conn;
    }
    
    /**
     * 上传文件 及 提交参数
     * 
     * @param uploadUrl
     * @param files
     * @param params
     * @param propertys
     * @return
     * @throws IOException
     */
	public static HttpURLConnection doUpload(String uploadUrl, Map<String,File> files, Map<String,Object> params, Map<String,String> propertys) throws IOException {
		URL url = new URL(uploadUrl);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		/* 允许Input、Output，不使用Cache */
		conn.setDoInput(true);
		conn.setDoOutput(true);
		conn.setUseCaches(false);
        conn.setConnectTimeout(TIME_OUT);
		/* 设置传送的method=POST */
		conn.setRequestMethod(SERVLET_POST);
		/* setRequestProperty */
		if (propertys!=null && !propertys.isEmpty()){
            for (String key : propertys.keySet()) {
            	conn.setRequestProperty(key, propertys.get(key));  
            }
        }
		conn.setRequestProperty(CONNECTION, KEEP_ALIVE);
		conn.setRequestProperty(CHARSET, UTF_8);
		conn.setRequestProperty(CONTENT_TYPE,MULTIPAT_FORMDATA);
		/* 设置DataOutputStream */
		DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
		
		/* 拼接参数 */
        if(params!=null && !params.isEmpty()){      
        	for(String key : params.keySet()){   
                ds.writeBytes(PREFIX + BOUNDARY + LINE_END);
    			ds.write(("Content-Disposition: form-data;" + "name=\"" + key + "\"" + LINE_END).getBytes(UTF_8));
    			ds.writeBytes(LINE_END);
    			ds.write(params.get(key).toString().getBytes(UTF_8));
    			ds.writeBytes(LINE_END);
        	}
        }
        
        /* 拼接文件  */
		if (files!=null && !files.isEmpty()){
            for (String key : files.keySet()) {
            	ds.writeBytes(PREFIX + BOUNDARY + LINE_END);
    			ds.write(("Content-Disposition: form-data;" + "name=\"" + key + "\";filename=\"" + files.get(key).getName() + "\"" + LINE_END).getBytes(UTF_8));
    			ds.writeBytes(LINE_END);
    			/* 取得文件的FileInputStream */
    			FileInputStream fStream = new FileInputStream(files.get(key));
    			/* 设置每次写入1024bytes */
    			int bufferSize = 1024;
    			byte[] buffer = new byte[bufferSize];
    			int length = -1;
    			/* 从文件读取数据至缓冲区 */
    			while ((length = fStream.read(buffer)) != -1) {
    				/* 将资料写入DataOutputStream中 */
    				ds.write(buffer, 0, length);
    			}
    			ds.writeBytes(LINE_END);
    			fStream.close();
            }
    		ds.writeBytes(PREFIX + BOUNDARY + PREFIX + LINE_END);
        }
        
		/* close streams */
		ds.flush();
		ds.close();
		
		return conn;
	}
	
	/**
	 * 下载文件
	 * 
	 * @param downloadUrl
	 * @param filePath
	 * @param params
	 * @param propertys
     * @return
	 * @throws IOException
	 */
	public static HttpURLConnection doDownload(String downloadUrl, Map<String,Object> params, Map<String,String> propertys) throws IOException{
		/*设置参数*/
		String paramStr = prepareParam(params);
    	if(paramStr!=null && !"".equals(paramStr)){
    		downloadUrl +="?"+paramStr;
        }
        URL url = new URL(downloadUrl);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod(SERVLET_GET);
        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setConnectTimeout(TIME_OUT);
        /*setRequestProperty*/
        if (propertys!=null && !propertys.isEmpty()){
            for (String key : propertys.keySet()) {
            	conn.setRequestProperty(key, propertys.get(key));
            }
        }
        conn.setRequestProperty(REFERER, url.toString());
        conn.setRequestProperty(CHARSET, UTF_8);
        conn.setRequestProperty(ACCEPT, ACCEPT_VALUE);
        conn.setRequestProperty(CONNECTION, KEEP_ALIVE);
        conn.setRequestProperty(RANGE, "bytes=0-");//从第几字节到第几个字节
        
		return conn;
	}
    
    /**
     * 获取返回内容
     * 
     * @param conn
     * @return
     * @throws IOException
     */
    public static String getString(HttpURLConnection conn) throws IOException{
    	StringBuffer result = new StringBuffer();
    	InputStreamReader input = new InputStreamReader(conn.getInputStream(), "utf-8");
		BufferedReader reader = new BufferedReader(input);
		String temp;
		while ((temp = reader.readLine()) != null) {
			result.append(temp).append("\n");
		}
		reader.close();
		input.close();
		return result.toString();
    }
    
    /**
     * 获取返回byte[]
     * 
     * @param conn
     * @return
     * @throws IOException 
     */
    public static byte[] getBytes(HttpURLConnection conn) throws IOException{
    	InputStream in = conn.getInputStream();
    	ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = in.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }
    
    /**
     * 获取返回文件
     * 
     * @param conn
     * @param filePath
     * @return
     * @throws IOException
     */
    public static File getFile(HttpURLConnection conn, String filePath) throws IOException{
    	/*下载文件*/
        InputStream in = conn.getInputStream();
        RandomAccessFile rf = new RandomAccessFile(filePath,"rw");
        rf.seek(0);
		byte[] b = new byte[204800];
		int n;
		while((n=in.read(b,0,1024)) > 0){
			rf.write(b,0,n);
		}
		rf.close();
		in.close();
		/*返回文件*/
		return new File(filePath);
    }
    
    /**
     * test
     * @param args
     */
//    public static void main(String[] args) {
//    	HttpURLConnection conn = null;
//    	try {
//    		Map<String, Object> params = new HashMap<String, Object>();
//    		params.put("token", "760");
//    		params.put("title", "你好1");
//    		params.put("content", "你好2");
//    		params.put("tickerText", "你好3");
//			conn = doGet("http://localhost:8080/ising/DDPush/push.app", params, null);
//			conn = doPost("http://localhost:8080/ising/DDPush/ppush.app", params, null);
//    		
//    		Map<String, File> files = new HashMap<String, File>();
//    		files.put("file1", new File("C:/Users/HuangChen/Desktop/软件测试题答案.docx"));
//    		conn = doUpload("http://localhost:8080/ising/file/upload.app", files, params,null);
//			conn = doDownload("http://localhost:8080/ising/file/download/5799bc4cc61c84a4deabd8fe.docx", null, null);
//			conn = doDelete("http://localhost:8080/ising/file/delete/5799bc4cc61c84a4deabd8fe.app", null, null);
//			if(conn!=null){
//				if(conn.getResponseCode()==200){
//					System.out.println(getString(conn));
//					System.out.println(getBytes(conn));
//					System.out.println(getFile(conn,"C:/Users/HuangChen/Desktop/test.docx"));
//				}else{
//					System.out.println(conn.getResponseCode());
//					System.out.println(conn.getResponseMessage());
//				}
//			}
//			conn.disconnect();
//		} catch (IOException e) {
//			e.printStackTrace();
//		}finally{
//			if(conn != null)
//				conn.disconnect();
//		}
//	}
    
}
